package edu.zcmu.seckill.service.impl;

import com.auth0.jwt.interfaces.DecodedJWT;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import edu.zcmu.seckill.entity.*;
import edu.zcmu.seckill.enumeration.GlobalEnum;
import edu.zcmu.seckill.enumeration.OrderStatusEnum;
import edu.zcmu.seckill.exception.MyException;
import edu.zcmu.seckill.mapper.OrderMapper;
import edu.zcmu.seckill.mapper.ProductMapper;
import edu.zcmu.seckill.response.R;
import edu.zcmu.seckill.response.ResultCode;
import edu.zcmu.seckill.service.*;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import edu.zcmu.seckill.utils.GetAgeUtil;
import edu.zcmu.seckill.utils.JwtUtil;
import edu.zcmu.seckill.utils.SnowFlake;
import edu.zcmu.seckill.vo.OrderVo;
import edu.zcmu.seckill.vo.PayVo;
import edu.zcmu.seckill.vo.ProductOrderVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;

import javax.servlet.http.HttpServletRequest;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.concurrent.ThreadPoolExecutor;

/**
 * <p>
 * 订单表 服务实现类
 * </p>
 *
 * @author 唐诗
 * @since 2022-02-22
 */
@Service
public class OrderServiceImpl extends ServiceImpl<OrderMapper, Order> implements OrderService {

    @Autowired
    JwtUtil jwtUtil;

    @Autowired
    ProductService productService;
    @Autowired
    ThreadPoolExecutor threadPoolExecutor;
    @Autowired
    UserService userService;
    @Autowired
    SysBankService sysBankService;
    @Autowired
    OrderPayLogService orderPayLogService;
    @Autowired
    ProductPolicyService productPolicyService;
    @Autowired
    ProductMapper productMapper;
    @Override
    public int createOrder(Order order) {
        baseMapper.insert(order);
        return 1;
    }

    @Override
    public synchronized R placeOrder(Integer id, HttpServletRequest request) {
        //获取用户token
        DecodedJWT tokenInfo = JwtUtil.getTokenInfo(request.getHeader(jwtUtil.getHeader()));
        String uid = tokenInfo.getClaim("id").asString();
        String policy = tokenInfo.getClaim("policy").asString();  //获得token中携带的用户筛选条件
        char[] chars = policy.toCharArray();
        String age = (String) tokenInfo.getClaim("age").asString();
        BaseMapper<ProductPolicy> baseMapper = productPolicyService.getBaseMapper();
        ProductPolicy policy1 = baseMapper.selectById(id);
        if (policy1==null){
            policy1=new ProductPolicy(id,1,1,1,18);
        }else if (policy1.getDishonesty()==null){
            policy1.setDishonesty(1);
        }else if(policy1.getAgeSize()==null){
            policy1.setAgeSize(18);

        }else if (policy1.getOverdue()==null){
            policy1.setOverdue(1);
        }else if (policy1.getJob()==null){
            policy1.setJob(1);
        }
        Integer ageSize = policy1.getAgeSize();
        if (Integer.valueOf(age)<ageSize){
            throw new MyException(ResultCode.ERROR,"年龄不符合条件");
        }
        if ("1".equals(chars[0])&&"1".equals(policy1.getOverdue().toString())){
            throw new MyException(ResultCode.ERROR,"存在近3年逾期2次以上");
        }
        if ("1".equals(chars[1])&&"1".equals(policy1.getJob().toString())){
            throw new MyException(ResultCode.ERROR,"失业人员不可购买");
        }
        if ("1".equals(chars[2])&&"1".equals(policy1.getDishonesty().toString())){
            throw new MyException(ResultCode.ERROR,"你已被列入失信人名单");
        }
        Order userOrder = this.baseMapper.selectOne(new LambdaQueryWrapper<Order>()
                .eq(id != null, Order::getProductId, id)
                .eq( Order::getUserId, uid));
        if (userOrder!=null){
            throw new MyException(ResultCode.ERROR,"该产品只能购买一份");
        }
        Product product = productService.getBaseMapper().selectById(id);
        Order order = Order.createOrder(product,uid);
        boolean save = save(order);
        if (save){
            return R.ok().data("data",order.getId());
        }else{
            return R.error();
        }

    }

    @Override
    public R getOrderInfo(OrderVo vo,HttpServletRequest request) {
        //获取用户token
        DecodedJWT tokenInfo = JwtUtil.getTokenInfo(request.getHeader(jwtUtil.getHeader()));
        String uid = tokenInfo.getClaim("id").asString();
        if (vo==null){
            throw new MyException(ResultCode.ERROR,"系统异常");
        }
        if (StringUtils.isEmpty(uid)){
            throw new MyException(ResultCode.ERROR,"用户信息异常");
        }
        String orderId = vo.getOrderId();
        Integer productId = vo.getProductId();
        Order userOrder = baseMapper.selectOne(new LambdaQueryWrapper<Order>()
                .eq( Order::getProductId, productId)
                .eq( Order::getUserId, uid)
                .eq(Order::getId,orderId));
        if (userOrder==null){
            throw new MyException(ResultCode.ERROR,"不存在该订单");
        }


        if (OrderStatusEnum.ORDER_PAID.getCode().equals(userOrder.getOrderStatus())){
            throw new MyException(ResultCode.ERROR,OrderStatusEnum.ORDER_PAID.getDescribe());
        }

        if (OrderStatusEnum.ORDER_OVERDUE.getCode().equals(userOrder.getOrderStatus())){
            throw new MyException(ResultCode.ERROR,OrderStatusEnum.ORDER_OVERDUE.getDescribe());
        }
        if (OrderStatusEnum.ORDER_MONEY_ERROR.getCode().equals(userOrder.getOrderStatus())){
            throw new MyException(ResultCode.ERROR,OrderStatusEnum.ORDER_MONEY_ERROR.getDescribe());
        }
        Product byId = productService.getById(productId);

        ProductOrderVo productOrderVo = ProductOrderVo.createProductOrderVo(userOrder, byId);

        return R.ok().data("data",productOrderVo);
    }
    @Transactional
    @Override
    public  synchronized Boolean payNormalOrder(OrderVo orderVo, HttpServletRequest request) {
        //获取用户token
        DecodedJWT tokenInfo = JwtUtil.getTokenInfo(request.getHeader(jwtUtil.getHeader()));

        String uid = tokenInfo.getClaim("id").asString();  //获得token中携带的用户id
        if (StringUtils.isEmpty(uid)){
            throw new MyException(ResultCode.ERROR,"用户账号异常，请重新登录");
        }

        if (orderVo==null){
            throw new MyException(ResultCode.ERROR,"当前系统状态异常");
        }
        String orderId = orderVo.getOrderId();
        Integer productId = orderVo.getProductId();

        Order order = baseMapper.selectById(orderId);

        if (order==null){
            throw  new MyException(ResultCode.ERROR,"订单异常，请联系客服");
        }
        Integer orderStatus = order.getOrderStatus();
        //判断订单状态
        if (orderStatus!=0){
            throw  new MyException(ResultCode.ERROR,"订单异常，请联系客服");
        }
        Boolean aBoolean = runPay(order,uid, orderVo, order.getTotalPrice());
        if (!aBoolean){
            throw  new MyException(ResultCode.ERROR,"支付失败");
        }
        return true;
    }
    @Transactional
    public Boolean runPay(Order order, String uid, OrderVo orderVo, BigDecimal price){
        User byId = userService.getById(uid);
        if (price!=null&&byId.getMoney()!=null&&byId.getMoney().compareTo(price)==-1){
            return false;
        }else {
            //修改用户金额
            User user = new User();
            user.setId(Integer.valueOf(uid));
            user.setMoney(byId.getMoney().subtract(price));
            userService.updateUser(user);
            //更改银行金额
            SysBank sysBank = new SysBank();
            sysBank.setBankName("三湘银行");
            sysBank.setUpdateTime( new Date());
            sysBank.setBankMoney(price);
            sysBankService.updateByMoney(sysBank);
            //更改订单状态
            Order order1 = new Order();
            order1.setId(orderVo.getOrderId());
            order1.setUserId(Integer.valueOf(uid));
            order1.setProductId(Integer.valueOf(orderVo.getProductId()));
            order1.setOrderStatus(OrderStatusEnum.ORDER_PAID.getCode());
            baseMapper.updateById(order1);
            productMapper.updateProductBySale(orderVo.getProductId(),1);
            //添加支付日志
            threadPoolExecutor.execute(()->{
                OrderPayLog OrderPayLog = new OrderPayLog();
                OrderPayLog.setOrderId(orderVo.getOrderId());
                OrderPayLog.setToalFee(price);
                OrderPayLog.setPayTime(new Date(System.currentTimeMillis()));
                OrderPayLog.setPayType(1);
                OrderPayLog.setCreateTime(new Date(System.currentTimeMillis()));
                orderPayLogService.getBaseMapper().insert(OrderPayLog);
            });
            return true;
        }
    }

}
